package com.xusheng.cli.controller;

import cn.dev33.satoken.session.SaSession;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.digest.DigestUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.xusheng.cli.common.annotation.OperationLogAnno;
import com.xusheng.cli.common.base.Result;
import com.xusheng.cli.common.base.UserInfoForSession;
import com.xusheng.cli.common.constant.Constant;
import com.xusheng.cli.common.enums.OperationType;
import com.xusheng.cli.entity.userModule.LoginInfoVO;
import com.xusheng.cli.entity.userModule.User;
import com.xusheng.cli.service.PermissionService;
import com.xusheng.cli.service.RoleService;
import com.xusheng.cli.service.UserService;
import com.xusheng.cli.tools.IpUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.List;


/**
 * 登录相关
 *
 * @author jy
 * @since 2020-04-11 14:57
 */
@Slf4j
@Validated
@RestController
@RequestMapping("/api/v1/login")
public class LoginController {

	@Resource
	private UserService userService;

	@Resource
	private RoleService roleService;

	@Resource
	private PermissionService permissionService;

	@PostMapping("/login")
	@OperationLogAnno(module = "登录模块", type = OperationType.LOGIN, desc = "登录")
	public Result<Object> login(@Validated @RequestBody LoginInfoVO loginInfoVO) {
		SaSession tokenSession = StpUtil.getTokenSession();
		Object attribute = tokenSession.get(Constant.CAPTCHA_SESSION_KEY);
		if (attribute == null) {
			return Result.error("验证码已失效,请刷新页面后重试!");
		}
		if (!StrUtil.equalsIgnoreCase((CharSequence) attribute, loginInfoVO.getVerificationCode())) {
			return Result.error("验证码不正确!");
		}
		tokenSession.delete(Constant.CAPTCHA_SESSION_KEY);
		LambdaQueryWrapper<User> wrapper = Wrappers.lambdaQuery();
		wrapper.eq(User::getAccount, loginInfoVO.getAccount()).eq(User::getEnable, true);
		User user = userService.getOne(wrapper);
		if (user == null) {
			return Result.error("账户或密码错误");
		}
		String password = user.getPassword();
		Assert.notBlank(password, "密码不能为空");
		boolean b = DigestUtil.bcryptCheck(loginInfoVO.getPassword(), password);
		if (b) {
			String ipWhitelist = userService.getIpWhitelist(user.getId());
			if (StrUtil.isNotBlank(ipWhitelist)) {
				String clientIp = IpUtil.getClientIp();
				log.info("总后台登录,ip:{}", clientIp);
				Assert.isTrue(ipWhitelist.contains(clientIp), "当前设备ip:{},无法登录", clientIp);
			}
			Long userId = user.getId();
			StpUtil.login(userId);
			StpUtil.getSession().set(Constant.USER, new UserInfoForSession(userId, user.getAccount(), user.getName()));
			return Result.success(StpUtil.getTokenValue());
		}
		return Result.error("账号或密码错误");
	}

	/**
	 * 获取当前登录人的角色
	 *
	 * @author jy
	 * @since 2022/1/18 10:45
	 */
	@GetMapping("/roles")
	public Result<List<String>> getRoles() {
		return Result.success(roleService.getRolesByUserId());
	}

	/**
	 * 获取当前登录人的页面权限
	 *
	 * @author jy
	 * @since 2022/1/18 10:45
	 */
	@GetMapping("/permission")
	public Result<List<String>> getPermissions() {
		return Result.success(permissionService.getAllPermissionUrlByUserId());
	}

	/**
	 * 获取当前登录人的按钮权限
	 *
	 * @author jy
	 * @since 2022/1/18 10:46
	 */
	@GetMapping("/btnPermission")
	public Result<List<String>> getBtnPermission() {
		return Result.success(permissionService.getAllBtnPermissionByUserId());
	}

	/**
	 * 登出
	 *
	 * @author jy
	 * @since 2022/1/18 16:15
	 */
	@GetMapping("/signOut")
	public Result<Object> signOut() {
		StpUtil.logout();
		return Result.success();
	}

}
